/**
 *
 */
package commons.beancopier.internal;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;


import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.ClassUtils;

import com.tmall.common.beancopier.AbstractPropertyCopier;
import com.tmall.common.beancopier.BeanCopier;
import com.tmall.common.beancopier.mapper.BeanMapperUtils;
import com.tmall.common.beancopier.mapper.PropertiesMapper;
import com.tmall.common.beancopier.mapper.PropertiesMapperBuilder;

/**
 * @author 陌铭(Phenix Huang)
 *
 */
public class MapPropertyCopier extends AbstractPropertyCopier {


    public MapPropertyCopier() {
        super();
    }

    public MapPropertyCopier(PropertiesMapperBuilder mapper, BeanCopier copier) {
        super(mapper, copier);
    }

    /*
     *
     * @see net.phenix.comp.util.beancopier.AbstractPropertyCopier#smartCopyProperty(java.lang.Object, java.lang.String, java.lang.Class, java.lang.Object)
     */
    public void smartCopyProperty(Object dest, String propertyName, Class<?> propertyType, Object value) throws Exception {
        Map<?, ?> mapValue = (Map<?, ?>)value ;
        Map<Object, Object> map = null ;
        if (PropertyUtils.isReadable(dest, propertyName)) {
            map = (HashMap<Object, Object>)PropertyUtils.getProperty(dest, propertyName);
        }
        if (map == null || map == Collections.EMPTY_MAP) {
            if (!PropertyUtils.isWriteable(dest, propertyName)) {
                return ;
            }
            map = new HashMap<Object, Object>();
            PropertyUtils.setProperty(dest, propertyName, map);
        }

        Map<String, String> propertyMap = Collections.emptyMap();
        for (Object key : mapValue.keySet()) {
            Object subSource = mapValue.get(key);
            Object subDest = null ;
            if (subSource != null) {
                if (propertyMap == Collections.EMPTY_MAP) {
                    PropertiesMapper mapper = getPropertyMapper(subSource.getClass());
                    if (mapper == null) {
                        return ;
                    }
                    propertyMap = BeanMapperUtils.getPropertyNameMap(subSource.getClass());
                    BeanMapperUtils.filterProperties(propertyMap, mapper);
                }
                subDest = cloneAndFilterObject(dest, subSource, subSource.getClass(), propertyMap);
            }
            map.put(key, subDest);
        }

    }

    /*
     * @see net.phenix.comp.util.beancopier.AbstractPropertyCopier#couldSmartCopy(java.lang.Class)
     */
    @Override
    public boolean couldSmartCopy(Class<?> propertyType) {
        return ClassUtils.isAssignable(propertyType, Map.class);
    }



}
